// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
//
// 本项目主要遵循 MIT 许可证和 Apache 许可证（版本 2.0）进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
//
// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动！任何基于本项目二次开发而产生的一切法律纠纷和责任，我们不承担任何责任！

using Admin.NET.Core.Service;
using Microsoft.AspNetCore.Http;
using Furion.DatabaseAccessor;
using Furion.FriendlyException;
using Mapster;
using SqlSugar;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
using Admin.NET.Application.Entity;
using Admin.NET.Application.Service.ShelfLife.Dto;
using Admin.NET.Core;
using System.Linq;
using Furion.DynamicApiController;
using Microsoft.AspNetCore.Mvc;

namespace Admin.NET.Application.Service.ShelfLife;

/// <summary>
/// 保质期管理服务 ⏰
/// </summary>
[ApiDescriptionSettings("保质期管理", Name = "ShelfLife", Order = 100)]
[Route("api/shelfLife")]
public class ShelfLifeService : IDynamicApiController, ITransient
{
    private readonly ISqlSugarClient _sqlSugarClient;
    private readonly SysDictDataService _sysDictDataService;

    public ShelfLifeService(ISqlSugarClient sqlSugarClient, SysDictDataService sysDictDataService)
    {
        _sqlSugarClient = sqlSugarClient;
        _sysDictDataService = sysDictDataService;
    }

    /// <summary>
    /// 分页查询保质期信息 📋
    /// </summary>
    /// <param name="input"></param>
    /// <returns></returns>
    [DisplayName("分页查询保质期信息")]
    [ApiDescriptionSettings(Name = "Page"), HttpPost]
    public async Task<SqlSugarPagedList<ShelfLifeOutput>> Page(GetShelfLifeInput input)
    {
        // 从货品表获取基本信息，并计算保质期状态
        var query = _sqlSugarClient.Queryable<GoodsModel>()
            .LeftJoin<WarehouseModel>((g, w) => g.GoodsWareId == w.Id)
            .LeftJoin<WarePlaceModel>((g, w, wp) => w.Id == wp.Id)
            .LeftJoin<GoodsTypeModel>((g, w, wp, gt) => g.GoodsTypeId == gt.Id)
            .WhereIF(!string.IsNullOrWhiteSpace(input.GoodsName), (g, w, wp, gt) => 
                g.GoodsName.Contains(input.GoodsName) || g.GoodsCode.Contains(input.GoodsName))
            .WhereIF(!string.IsNullOrWhiteSpace(input.Batch), (g, w, wp, gt) => 
                g.GoodsCode.Contains(input.Batch)) // 假设批次信息存储在货品编号中
            .WhereIF(!string.IsNullOrWhiteSpace(input.Barcode), (g, w, wp, gt) => 
                g.GoodsCode.Contains(input.Barcode)) // 假设条码信息存储在货品编号中
            .WhereIF(!string.IsNullOrWhiteSpace(input.GoodsType), (g, w, wp, gt) => 
                g.GoodsTypeId.ToString().Contains(input.GoodsType))
            .WhereIF(!string.IsNullOrWhiteSpace(input.Unit), (g, w, wp, gt) => 
                g.GoodsUnitId.ToString().Contains(input.Unit))
            .WhereIF(!string.IsNullOrWhiteSpace(input.WarehouseName), (g, w, wp, gt) => 
                w.WareName.Contains(input.WarehouseName))
            .Select((g, w, wp, gt) => new ShelfLifeOutput
            {
                Id = g.Id,
                GoodsCode = g.GoodsCode,
                GoodsName = g.GoodsName,
                Status = "正常", // 将在后续计算
                GoodsType = gt.GoodsTypeName ?? g.GoodsTypeId.ToString(),
                Specs = g.GoodsSpecs,
                Unit = g.GoodsUnitId.ToString(), // 先使用ID，后续会通过字典服务获取名称
                WarehouseName = w.WareName,
                LocationName = wp.WarePlaceName,
                Barcode = g.GoodsCode, // 使用货品编号作为条码
                CurrentStock = 50, // 默认库存
                Batch = 1, // 默认批次
                ProductionDate = DateTime.Now.AddDays(-30).ToString("yyyy-MM-dd"), // 默认生产日期
                ExpirationDate = DateTime.Now.AddDays(30).ToString("yyyy-MM-dd"), // 默认到期日期
                RemainingDays = 30, // 将在后续计算
                ShelfLifeDays = 365, // 默认保质期365天
                WarningDays = 30 // 默认预警天数30天
            });

        var result = await query.ToPagedListAsync(input.Page, input.PageSize);

        // 为每个货品计算保质期状态
        foreach (var item in result.Items)
        {
            await CalculateShelfLifeStatus(item, input);
        }

        // 获取货品单位字典数据（使用与库存查询相同的方式）
        var goodsUnitDict = await _sysDictDataService.GetDataList("GoodsEnumm");
        
        // 映射货品单位名称（完全按照库存查询的逻辑）
        foreach (var item in result.Items)
        {
            if (!string.IsNullOrEmpty(item.Unit))
            {
                // 按照库存查询的逻辑：优先匹配 value，然后匹配 id
                var unit = goodsUnitDict?.FirstOrDefault(u => 
                    u.Value == item.Unit || u.Id.ToString() == item.Unit);
                
                if (unit != null)
                {
                    // 按照库存查询的逻辑：优先使用 label，如果没有则使用 name
                    item.Unit = !string.IsNullOrEmpty(unit.Label) ? unit.Label : unit.Name ?? item.Unit;
                }
            }
        }

        return result;
    }

    /// <summary>
    /// 计算保质期状态
    /// </summary>
    /// <param name="item"></param>
    /// <param name="input"></param>
    /// <returns></returns>
    private async Task CalculateShelfLifeStatus(ShelfLifeOutput item, GetShelfLifeInput input)
    {
        // 模拟计算剩余天数
        var today = DateTime.Now;
        var expirationDate = DateTime.Parse(item.ExpirationDate);
        var remainingDays = (expirationDate - today).Days;

        item.RemainingDays = remainingDays;

        // 根据剩余天数确定状态
        if (remainingDays < 0)
        {
            item.Status = "已到期";
        }
        else if (remainingDays <= 7)
        {
            item.Status = "即将到期";
        }
        else
        {
            item.Status = "正常";
        }

        // 根据状态筛选
        if (!string.IsNullOrWhiteSpace(input.Status))
        {
            if (input.Status != item.Status)
            {
                item.Status = ""; // 标记为不匹配
            }
        }

        // 根据到期日期筛选
        if (input.ExpirationDateStart.HasValue)
        {
            if (expirationDate < input.ExpirationDateStart.Value)
            {
                item.Status = ""; // 标记为不匹配
            }
        }

        if (input.ExpirationDateEnd.HasValue)
        {
            if (expirationDate > input.ExpirationDateEnd.Value)
            {
                item.Status = ""; // 标记为不匹配
            }
        }
    }

    /// <summary>
    /// 导出保质期数据 📊
    /// </summary>
    /// <param name="input"></param>
    /// <returns></returns>
    [DisplayName("导出保质期数据")]
    [ApiDescriptionSettings(Name = "Export"), HttpPost, NonUnify]
    public async Task<IActionResult> Export(GetShelfLifeInput input)
    {
        // 获取所有保质期数据（不分页）
        var query = _sqlSugarClient.Queryable<GoodsModel>()
            .LeftJoin<WarehouseModel>((g, w) => g.GoodsWareId == w.Id)
            .LeftJoin<WarePlaceModel>((g, w, wp) => w.Id == wp.Id)
            .LeftJoin<GoodsTypeModel>((g, w, wp, gt) => g.GoodsTypeId == gt.Id)
            .WhereIF(!string.IsNullOrWhiteSpace(input.GoodsName), (g, w, wp, gt) => 
                g.GoodsName.Contains(input.GoodsName) || g.GoodsCode.Contains(input.GoodsName))
            .WhereIF(!string.IsNullOrWhiteSpace(input.Batch), (g, w, wp, gt) => 
                g.GoodsCode.Contains(input.Batch))
            .WhereIF(!string.IsNullOrWhiteSpace(input.Barcode), (g, w, wp, gt) => 
                g.GoodsCode.Contains(input.Barcode))
            .WhereIF(!string.IsNullOrWhiteSpace(input.GoodsType), (g, w, wp, gt) => 
                g.GoodsTypeId.ToString().Contains(input.GoodsType))
            .WhereIF(!string.IsNullOrWhiteSpace(input.Unit), (g, w, wp, gt) => 
                g.GoodsUnitId.ToString().Contains(input.Unit))
            .WhereIF(!string.IsNullOrWhiteSpace(input.WarehouseName), (g, w, wp, gt) => 
                w.WareName.Contains(input.WarehouseName))
            .Select((g, w, wp, gt) => new ShelfLifeOutput
            {
                Id = g.Id,
                GoodsCode = g.GoodsCode,
                GoodsName = g.GoodsName,
                Status = "正常",
                GoodsType = gt.GoodsTypeName ?? g.GoodsTypeId.ToString(),
                Specs = g.GoodsSpecs,
                Unit = g.GoodsUnitId.ToString(), // 先使用ID，后续会通过字典服务获取名称
                WarehouseName = w.WareName,
                LocationName = wp.WarePlaceName,
                Barcode = g.GoodsCode,
                CurrentStock = 50,
                Batch = 1,
                ProductionDate = DateTime.Now.AddDays(-30).ToString("yyyy-MM-dd"),
                ExpirationDate = DateTime.Now.AddDays(30).ToString("yyyy-MM-dd"),
                RemainingDays = 30,
                ShelfLifeDays = 365, // 默认保质期365天
                WarningDays = 30 // 默认预警天数30天
            });

        var allData = await query.ToListAsync();

        // 为每个货品计算保质期状态
        foreach (var item in allData)
        {
            await CalculateShelfLifeStatus(item, input);
        }

        // 获取货品单位字典数据（使用与库存查询相同的方式）
        var goodsUnitDict = await _sysDictDataService.GetDataList("GoodsEnumm");
        
        // 映射货品单位名称（完全按照库存查询的逻辑）
        foreach (var item in allData)
        {
            if (!string.IsNullOrEmpty(item.Unit))
            {
                // 按照库存查询的逻辑：优先匹配 value，然后匹配 id
                var unit = goodsUnitDict?.FirstOrDefault(u => 
                    u.Value == item.Unit || u.Id.ToString() == item.Unit);
                
                if (unit != null)
                {
                    // 按照库存查询的逻辑：优先使用 label，如果没有则使用 name
                    item.Unit = !string.IsNullOrEmpty(unit.Label) ? unit.Label : unit.Name ?? item.Unit;
                }
            }
        }

        // 转换为导出格式
        var exportList = allData.Adapt<List<ExportShelfLifeOutput>>();
        
        // 使用ExcelHelper导出，参考客户管理的方式
        return ExcelHelper.ExportTemplate(exportList, "保质期管理数据");
    }

    /// <summary>
    /// 获取单位列表
    /// </summary>
    /// <returns></returns>
    [DisplayName("获取单位列表")]
    [ApiDescriptionSettings(Name = "GetUnits"), HttpGet]
    public async Task<List<object>> GetUnits()
    {
        try
        {
            // 从字典数据中获取货品单位枚举
            var units = await _sysDictDataService.GetDataList("GoodsEnumm");
            
            if (units != null && units.Any())
            {
                return units.Select(u => new
                {
                    id = u.Id,
                    value = u.Value,
                    label = !string.IsNullOrEmpty(u.Label) ? u.Label : u.Name,
                    name = u.Name
                }).Cast<object>().ToList();
            }
            else
            {
                // 如果字典中没有数据，返回默认单位
                return new List<object>
                {
                    new { id = 1, value = "1", label = "台", name = "台" },
                    new { id = 2, value = "2", label = "个", name = "个" },
                    new { id = 3, value = "3", label = "件", name = "件" },
                    new { id = 4, value = "4", label = "箱", name = "箱" },
                    new { id = 5, value = "5", label = "包", name = "包" },
                    new { id = 6, value = "6", label = "瓶", name = "瓶" },
                    new { id = 7, value = "7", label = "盒", name = "盒" },
                    new { id = 8, value = "8", label = "套", name = "套" },
                    new { id = 9, value = "9", label = "袋", name = "袋" },
                    new { id = 10, value = "10", label = "公斤", name = "公斤" }
                };
            }
        }
        catch (Exception ex)
        {
            throw Oops.Oh($"获取单位列表失败: {ex.Message}");
        }
    }

    /// <summary>
    /// 获取仓库列表
    /// </summary>
    /// <returns></returns>
    [DisplayName("获取仓库列表")]
    [ApiDescriptionSettings(Name = "GetWarehouses"), HttpGet]
    public async Task<List<object>> GetWarehouses()
    {
        try
        {
            var warehouses = await _sqlSugarClient.Queryable<WarehouseModel>()
                .Select(w => new { w.Id, w.WareName })
                .ToListAsync();
            
            return warehouses.Select(w => new
            {
                id = w.Id,
                value = w.Id.ToString(),
                label = w.WareName,
                name = w.WareName
            }).Cast<object>().ToList();
        }
        catch (Exception ex)
        {
            throw Oops.Oh($"获取仓库列表失败: {ex.Message}");
        }
    }
}
